<template>
  <div class="tetris-game" tabindex="0" @keydown="handleKeyDown" @keyup="handleKeyUp" ref="gameContainer">
    <div class="game-info">
      <div class="score-display">
        <span class="score">分数: <strong>{{ score }}</strong></span>
        <span class="level">等级: <strong>{{ level }}</strong></span>
        <span class="lines">消除行数: <strong>{{ linesCleared }}</strong></span>
      </div>
      <button class="restart-button" @click="resetGame">重新开始</button>
    </div>
    <div class="game-area">
      <!-- 左侧面板 -->
      <div class="left-panel">
        <div class="hold-piece-display">
          <h3>保留区</h3>
          <canvas ref="holdPieceCanvas" width="120" height="120"></canvas>
        </div>
      </div>
      
      <!-- 主游戏区域 -->
      <canvas ref="gameCanvas" width="300" height="600"></canvas>
      
      <!-- 右侧面板 -->
      <div class="right-panel">
        <div class="next-piece-display">
          <h3>下一个方块</h3>
          <canvas ref="nextPieceCanvas" width="120" height="120"></canvas>
        </div>
        <div class="time-display">
          <h3>游戏时间: <strong>{{ formattedTime }}</strong></h3>
        </div>
        <div class="controls">
          <h3>操作说明</h3>
          <p>← → : 左右移动</p>
          <p>↑ : 旋转</p>
          <p>↓ : 加速下落</p>
          <p>Shift : 直接落到底部</p>
          <p>空格 : 暂停/继续</p>
          <p>R : 重新开始游戏</p>
          <p>C : 保留方块<br>按C键可将当前下落的方块存入"保留区"<br>并立即取出下一个方块（若保留区为空则随机生成新方块）</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
// 方块形状定义
const SHAPES = [
  { shape: [[1, 1, 1, 1]], color: "#00FFFF", name: "I" }, // 青色
  { shape: [[1, 1], [1, 1]], color: "#FFFF00", name: "O" }, // 黄色
  { shape: [[0, 1, 0], [1, 1, 1]], color: "#800080", name: "T" }, // 紫色
  { shape: [[1, 0, 0], [1, 1, 1]], color: "#0000FF", name: "J" }, // 蓝色
  { shape: [[0, 0, 1], [1, 1, 1]], color: "#FF7F00", name: "L" }, // 橙色
  { shape: [[0, 1, 1], [1, 1, 0]], color: "#FF0000", name: "S" }, // 红色
  { shape: [[1, 1, 0], [0, 1, 1]], color: "#00FF00", name: "Z" }  // 绿色
];

// 方块类
class Tetromino {
  constructor(shape, color) {
    this.shape = shape;
    this.color = color;
    this.x = 0;
    this.y = 0;
  }

  // 旋转方法
  rotate() {
    const N = this.shape.length;
    const newShape = Array.from({ length: this.shape[0].length }, () => Array(N).fill(0));
    
    for (let i = 0; i < N; i++) {
      for (let j = 0; j < this.shape[i].length; j++) {
        newShape[j][N - 1 - i] = this.shape[i][j];
      }
    }
    
    return newShape;
  }
}

export default {
  name: "TetrisGame",
  data() {
    return {
      // 画布相关
      canvas: null,
      ctx: null,
      nextPieceCanvas: null,
      nextPieceCtx: null,
      holdPieceCanvas: null,
      holdPieceCtx: null,
      
      // 游戏状态
      grid: Array.from({ length: 20 }, () => Array(10).fill(0)),
      currentPiece: null,
      nextPiece: null,
      holdPiece: null,
      canHold: true,
      
      // 游戏统计
      score: 0,
      level: 1,
      linesCleared: 0,
      elapsedTime: 0,
      
      // 游戏控制
      isGameRunning: false,
      isPaused: false,
      isSoftDropping: false,
      isHardDropping: false,
      
      // 游戏速度
      baseDropSpeed: 1000,
      dropSpeed: 1000,
      dropAccumulator: 0,
      
      // 动画相关
      lastFrameTime: 0,
      animationFrameId: null,
      timeInterval: null,
      startTime: 0
    };
  },
  computed: {
    formattedTime() {
      const totalSeconds = Math.floor(this.elapsedTime / 1000);
      const minutes = Math.floor(totalSeconds / 60);
      const seconds = totalSeconds % 60;
      return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    }
  },
  mounted() {
    this.initGame();
    this.focusGameContainer();
  },
  beforeUnmount() {
    this.cleanup();
  },
  methods: {
    /**
     * 初始化游戏
     */
    initGame() {
      this.setupCanvases();
      this.resetGame();
    },
    
    /**
     * 设置画布
     */
    setupCanvases() {
      this.canvas = this.$refs.gameCanvas;
      this.ctx = this.canvas.getContext("2d");
      this.nextPieceCanvas = this.$refs.nextPieceCanvas;
      this.nextPieceCtx = this.nextPieceCanvas.getContext("2d");
      this.holdPieceCanvas = this.$refs.holdPieceCanvas;
      this.holdPieceCtx = this.holdPieceCanvas.getContext("2d");
      
      // 设置画布显示大小
      this.canvas.style.width = "300px";
      this.canvas.style.height = "600px";
      this.nextPieceCanvas.style.width = "120px";
      this.nextPieceCanvas.style.height = "120px";
      this.holdPieceCanvas.style.width = "120px";
      this.holdPieceCanvas.style.height = "120px";
    },
    
    /**
     * 聚焦游戏容器
     */
    focusGameContainer() {
      if (this.$refs.gameContainer) {
        this.$refs.gameContainer.focus();
      }
    },
    
    /**
     * 开始游戏
     */
    startGame() {
      if (this.isGameRunning) return;
      
      this.isGameRunning = true;
      this.isPaused = false;
      this.startTime = Date.now() - this.elapsedTime;
      this.timeInterval = setInterval(this.updateTime, 100);
      this.lastFrameTime = performance.now();
      this.dropAccumulator = 0;
      this.gameLoop(this.lastFrameTime);
      this.focusGameContainer();
    },
    
    /**
     * 游戏主循环
     */
    gameLoop(timestamp) {
      if (!this.isGameRunning) {
        this.animationFrameId = null;
        return;
      }
      
      if (!this.lastFrameTime) this.lastFrameTime = timestamp;
      
      if (!this.isPaused) {
        const deltaTime = timestamp - this.lastFrameTime;
        this.lastFrameTime = timestamp;
        
        this.dropAccumulator += deltaTime;
        
        if (this.isHardDropping) {
          this.hardDrop();
          this.isHardDropping = false;
        } 
        else if (this.isSoftDropping || this.dropAccumulator >= this.dropSpeed) {
          this.dropPiece();
          this.dropAccumulator = 0;
        }
      }
      
      this.draw();
      this.animationFrameId = requestAnimationFrame(this.gameLoop);
    },
    
    /**
     * 停止游戏
     */
    stopGame() {
      this.isGameRunning = false;
      clearInterval(this.timeInterval);
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
        this.animationFrameId = null;
      }
    },
    
    /**
     * 重置游戏
     */
    resetGame() {
      this.stopGame();
      
      // 重置游戏状态
      this.grid = Array.from({ length: 20 }, () => Array(10).fill(0));
      this.score = 0;
      this.level = 1;
      this.linesCleared = 0;
      this.dropSpeed = this.calculateDropSpeed();
      this.elapsedTime = 0;
      this.isPaused = false;
      this.isSoftDropping = false;
      this.isHardDropping = false;
      this.dropAccumulator = 0;
      this.lastFrameTime = 0;
      this.currentPiece = null;
      this.nextPiece = null;
      this.holdPiece = null;
      this.canHold = true;
      
      // 初始化新方块
      this.newPiece();
      this.newPiece();
      this.drawHoldPiece();
      
      // 开始游戏
      this.startGame();
    },
    
    /**
     * 创建新方块
     */
    newPiece() {
      if (!this.nextPiece) {
        this.nextPiece = this.createRandomPiece();
      }
      
      this.currentPiece = this.nextPiece;
      this.currentPiece.x = Math.floor((10 - this.currentPiece.shape[0].length) / 2);
      this.currentPiece.y = -this.currentPiece.shape.length;
      
      // 检查新方块是否可以放置（游戏是否结束）
      if (!this.validMove(this.currentPiece, this.currentPiece.x, this.currentPiece.y)) {
        // 尝试向上移动一行
        if (this.validMove(this.currentPiece, this.currentPiece.x, this.currentPiece.y + 1)) {
          this.currentPiece.y += 1;
        } else {
          // 如果仍然无法放置，游戏结束
          this.gameOver();
          return;
        }
      }
      
      this.nextPiece = this.createRandomPiece();
      this.canHold = true;
      this.drawNextPiece();
    },
    
    /**
     * 创建随机方块
     */
    createRandomPiece() {
      const randomIndex = Math.floor(Math.random() * SHAPES.length);
      const { shape, color } = SHAPES[randomIndex];
      return new Tetromino(shape.map(row => [...row]), color);
    },
    
    /**
     * 方块下落
     */
    dropPiece() {
      if (this.validMove(this.currentPiece, this.currentPiece.x, this.currentPiece.y + 1)) {
        this.currentPiece.y++;
        this.draw();
      } else {
        this.lockPiece();
      }
    },
    
    /**
     * 快速下落
     */
    hardDrop() {
      while (this.validMove(this.currentPiece, this.currentPiece.x, this.currentPiece.y + 1)) {
        this.currentPiece.y++;
      }
      this.lockPiece();
    },
    
    /**
     * 锁定方块到网格
     */
    async lockPiece() {
      // 添加下落动画
      const originalY = this.currentPiece.y;
      const targetY = this.calculateGhostPosition().y;
      
      if (targetY > originalY) {
        const duration = 100;
        const startTime = performance.now();
        
        const animate = (currentTime) => {
          const elapsed = currentTime - startTime;
          const progress = Math.min(elapsed / duration, 1);
          
          this.currentPiece.y = originalY + (targetY - originalY) * progress;
          this.draw();
          
          if (progress < 1) {
            requestAnimationFrame(animate);
          } else {
            this.finalizeLock();
          }
        };
        
        requestAnimationFrame(animate);
      } else {
        this.finalizeLock();
      }
    },

    finalizeLock() {
      // 检查游戏是否结束（方块是否超出顶部边界）
      let gameShouldEnd = false;
      
      this.currentPiece.shape.forEach((row, dy) => {
        row.forEach((value, dx) => {
          if (value) {
            const gridY = this.currentPiece.y + dy;
            const gridX = this.currentPiece.x + dx;
            
            // 如果方块的一部分在网格上方（y < 0），游戏应该结束
            if (gridY < 0) {
              gameShouldEnd = true;
            }
            
            // 只在y >=0时才填充网格
            if (gridY >= 0) {
              this.grid[gridY][gridX] = this.currentPiece.color;
            }
          }
        });
      });
      
      if (gameShouldEnd) {
        this.gameOver();
        return;
      }
      
      this.clearLines();
      this.newPiece();
    },
    
    /**
     * 清除完整的行
     */
    clearLines() {
      const newGrid = this.grid.filter(row => row.some(cell => cell === 0));
      const linesCleared = 20 - newGrid.length;
      
      if (linesCleared > 0) {
        this.linesCleared += linesCleared;
        this.score += this.calculateScore(linesCleared);
        
        const newLevel = Math.floor(this.linesCleared / 10) + 1;
        if (newLevel > this.level) {
          this.level = newLevel;
          this.dropSpeed = this.calculateDropSpeed();
        }
        
        // 添加新的空行
        for (let i = 0; i < linesCleared; i++) {
          newGrid.unshift(Array(10).fill(0));
        }
        
        this.grid = newGrid;
      }
    },
    
    /**
     * 计算得分
     */
    calculateScore(lines) {
      const points = [0, 40, 100, 300, 1200];
      return points[lines] * this.level;
    },
    
    /**
     * 计算下落速度
     */
    calculateDropSpeed() {
      return Math.max(50, this.baseDropSpeed - (this.level - 1) * 50);
    },
    
    /**
     * 旋转当前方块
     */
    rotateCurrentPiece() {
      const rotatedShape = this.currentPiece.rotate();
      const rotatedPiece = new Tetromino(rotatedShape, this.currentPiece.color);
      rotatedPiece.x = this.currentPiece.x;
      rotatedPiece.y = this.currentPiece.y;
      
      if (this.validMove(rotatedPiece, rotatedPiece.x, rotatedPiece.y)) {
        this.currentPiece.shape = rotatedShape;
      } else {
        // 尝试墙踢（wall kick）
        for (let offset of [-1, 1, -2, 2]) {
          if (this.validMove(rotatedPiece, rotatedPiece.x + offset, rotatedPiece.y)) {
            this.currentPiece.shape = rotatedShape;
            this.currentPiece.x += offset;
            break;
          }
        }
      }
    },
    
    /**
     * 检查移动是否有效
     */
    validMove(piece, x, y) {
      return piece.shape.every((row, dy) => {
        return row.every((value, dx) => {
          if (!value) return true;
          const newX = x + dx;
          const newY = y + dy;
          
          // 检查是否超出左右边界
          if (newX < 0 || newX >= 10) return false;
          
          // 检查是否超出底部边界
          if (newY >= 20) return false;
          
          // 检查是否与已有方块重叠（只检查网格内的位置）
          if (newY >= 0 && this.grid[newY][newX]) return false;
          
          return true;
        });
      });
    },
    
    /**
     * 保留当前方块
     */
    holdCurrentPiece() {
      if (!this.canHold) return;
      
      if (!this.holdPiece) {
        this.holdPiece = this.currentPiece;
        this.newPiece();
      } else {
        const temp = this.currentPiece;
        this.currentPiece = this.holdPiece;
        this.currentPiece.x = Math.floor((10 - this.currentPiece.shape[0].length) / 2);
        this.currentPiece.y = 0;
        this.holdPiece = temp;
      }
      
      this.canHold = false;
      this.drawHoldPiece();
    },
    
    /**
     * 计算幽灵方块位置（预览下落位置）
     */
    calculateGhostPosition() {
      if (!this.currentPiece) return { x: 0, y: 0 };
      
      let ghostY = this.currentPiece.y;
      while (this.validMove(this.currentPiece, this.currentPiece.x, ghostY + 1)) {
        ghostY++;
      }
      
      return {
        x: this.currentPiece.x,
        y: ghostY
      };
    },
    
    /**
     * 绘制游戏
     */
    draw() {
      this.clearCanvas();
      this.drawGrid();
      this.drawGhostPiece();
      this.drawCurrentPiece();
      this.drawGridLines();
      
      if (this.isPaused) {
        this.drawPauseScreen();
      }
    },
    
    /**
     * 清空画布
     */
    clearCanvas() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      this.ctx.fillStyle = "#1E1E1E";
      this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    },
    
    /**
     * 绘制网格
     */
    drawGrid() {
      this.grid.forEach((row, y) => {
        row.forEach((cell, x) => {
          if (cell) {
            this.drawBlock(x, y, cell);
          }
        });
      });
    },
    
    /**
     * 绘制幽灵方块
     */
    drawGhostPiece() {
      if (!this.currentPiece) return;
      
      const ghostPos = this.calculateGhostPosition();
      
      // 绘制下落轨迹线
      this.ctx.strokeStyle = this.currentPiece.color;
      this.ctx.lineWidth = 1;
      this.ctx.setLineDash([3, 3]);
      
      this.currentPiece.shape.forEach((row, dy) => {
        row.forEach((value, dx) => {
          if (value) {
            const fromX = (this.currentPiece.x + dx) * 30 + 15;
            const fromY = (this.currentPiece.y + dy) * 30 + 15;
            const toX = (ghostPos.x + dx) * 30 + 15;
            const toY = (ghostPos.y + dy) * 30 + 15;
            
            if (fromY < toY) { // 只绘制向下的线
              this.ctx.beginPath();
              this.ctx.moveTo(fromX, fromY);
              this.ctx.lineTo(toX, toY);
              this.ctx.stroke();
            }
          }
        });
      });
      
      this.ctx.setLineDash([]);
      
      // 绘制幽灵方块
      this.currentPiece.shape.forEach((row, dy) => {
        row.forEach((value, dx) => {
          if (value) {
            const x = ghostPos.x + dx;
            const y = ghostPos.y + dy;
            if (y >= 0) {
              this.drawGhostBlock(x, y, this.currentPiece.color);
            }
          }
        });
      });
    },
    
    /**
     * 绘制当前方块
     */
    drawCurrentPiece() {
      if (!this.currentPiece) return;
      
      this.currentPiece.shape.forEach((row, dy) => {
        row.forEach((value, dx) => {
          if (value) {
            const x = this.currentPiece.x + dx;
            const y = this.currentPiece.y + dy;
            if (y >= 0) {
              this.drawBlock(x, y, this.currentPiece.color);
            }
          }
        });
      });
    },
    
    /**
     * 绘制网格线
     */
    drawGridLines() {
      this.ctx.strokeStyle = "#333";
      this.ctx.lineWidth = 0.5;
      
      // 垂直线
      for (let i = 0; i <= 10; i++) {
        this.ctx.beginPath();
        this.ctx.moveTo(i * 30, 0);
        this.ctx.lineTo(i * 30, 600);
        this.ctx.stroke();
      }
      
      // 水平线
      for (let j = 0; j <= 20; j++) {
        this.ctx.beginPath();
        this.ctx.moveTo(0, j * 30);
        this.ctx.lineTo(300, j * 30);
        this.ctx.stroke();
      }
    },
    
    /**
     * 绘制暂停屏幕
     */
    drawPauseScreen() {
      this.ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
      this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
      
      // 添加模糊效果
      this.ctx.filter = "blur(2px)";
      this.drawGrid();
      this.drawCurrentPiece();
      this.ctx.filter = "none";
      
      // 绘制暂停文字
      this.ctx.fillStyle = "white";
      this.ctx.font = "bold 36px 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif";
      this.ctx.textAlign = "center";
      this.ctx.textBaseline = "middle";
      
      // 文字阴影
      this.ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
      this.ctx.shadowBlur = 10;
      this.ctx.shadowOffsetX = 2;
      this.ctx.shadowOffsetY = 2;
      
      this.ctx.fillText("游戏暂停", this.canvas.width / 2, this.canvas.height / 2 - 30);
      
      this.ctx.font = "18px 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif";
      this.ctx.fillText("按 空格 键继续", this.canvas.width / 2, this.canvas.height / 2 + 20);
      
      // 重置阴影
      this.ctx.shadowColor = "transparent";
    },
    
    /**
     * 绘制方块
     */
    drawBlock(x, y, color) {
      const size = 30;
      const padding = 2;
      
      this.ctx.fillStyle = color;
      this.ctx.fillRect(x * size, y * size, size, size);
      
      this.ctx.fillStyle = "rgba(255, 255, 255, 0.2)";
      this.ctx.fillRect(x * size + padding, y * size + padding, size - padding * 2, size - padding * 2);
      
      this.ctx.setLineDash([]);
    },
    
    /**
     * 绘制幽灵方块
     */
    drawGhostBlock(x, y, color) {
      const size = 30;
      const padding = 2;
      
      // 使用更明显的边框
      this.ctx.strokeStyle = color;
      this.ctx.lineWidth = 2;
      this.ctx.setLineDash([]);
      this.ctx.strokeRect(x * size + 1, y * size + 1, size - 2, size - 2);
      
      // 半透明填充
      this.ctx.fillStyle = color.replace(")", ", 0.1)").replace("rgb", "rgba");
      this.ctx.fillRect(x * size, y * size, size, size);
      
      // 内部小方块
      this.ctx.fillStyle = color.replace(")", ", 0.3)").replace("rgb", "rgba");
      this.ctx.fillRect(x * size + padding, y * size + padding, size - padding * 2, size - padding * 2);
      
      // 添加四个角标记
      const cornerSize = 6;
      this.ctx.fillStyle = color;
      // 左上角
      this.ctx.fillRect(x * size, y * size, cornerSize, cornerSize);
      // 右上角
      this.ctx.fillRect(x * size + size - cornerSize, y * size, cornerSize, cornerSize);
      // 左下角
      this.ctx.fillRect(x * size, y * size + size - cornerSize, cornerSize, cornerSize);
      // 右下角
      this.ctx.fillRect(x * size + size - cornerSize, y * size + size - cornerSize, cornerSize, cornerSize);
    },
    
    /**
     * 绘制下一个方块
     */
    drawNextPiece() {
      this.nextPieceCtx.clearRect(0, 0, this.nextPieceCanvas.width, this.nextPieceCanvas.height);
      this.nextPieceCtx.fillStyle = "#1E1E1E";
      this.nextPieceCtx.fillRect(0, 0, this.nextPieceCanvas.width, this.nextPieceCanvas.height);
      
      const offsetX = (4 - this.nextPiece.shape[0].length) * 15;
      const offsetY = (4 - this.nextPiece.shape.length) * 15;
      
      this.nextPiece.shape.forEach((row, dy) => {
        row.forEach((value, dx) => {
          if (value) {
            this.nextPieceCtx.fillStyle = this.nextPiece.color;
            this.nextPieceCtx.fillRect(
              dx * 30 + offsetX,
              dy * 30 + offsetY,
              30, 30
            );
          }
        });
      });
    },
    
    /**
     * 绘制保留方块
     */
    drawHoldPiece() {
      this.holdPieceCtx.clearRect(0, 0, this.holdPieceCanvas.width, this.holdPieceCanvas.height);
      this.holdPieceCtx.fillStyle = "#1E1E1E";
      this.holdPieceCtx.fillRect(0, 0, this.holdPieceCanvas.width, this.holdPieceCanvas.height);
      
      if (this.holdPiece) {
        const offsetX = (4 - this.holdPiece.shape[0].length) * 15;
        const offsetY = (4 - this.holdPiece.shape.length) * 15;
        
        this.holdPiece.shape.forEach((row, dy) => {
          row.forEach((value, dx) => {
            if (value) {
              this.holdPieceCtx.fillStyle = this.holdPiece.color;
              this.holdPieceCtx.fillRect(
                dx * 30 + offsetX,
                dy * 30 + offsetY,
                30, 30
              );
            }
          });
        });
      }
    },
    
    /**
     * 更新时间
     */
    updateTime() {
      if (!this.isPaused) {
        this.elapsedTime = Date.now() - this.startTime;
      }
    },
    
    /**
     * 处理键盘按下事件
     */
    handleKeyDown(event) {
      if (!this.isGameRunning && event.key !== 'r' && event.key !== 'R') return;
      
      switch (event.key) {
        case "ArrowLeft":
          if (!this.isPaused && this.validMove(this.currentPiece, this.currentPiece.x - 1, this.currentPiece.y)) {
            this.currentPiece.x--;
          }
          break;
        case "ArrowRight":
          if (!this.isPaused && this.validMove(this.currentPiece, this.currentPiece.x + 1, this.currentPiece.y)) {
            this.currentPiece.x++;
          }
          break;
        case "ArrowDown":
          this.isSoftDropping = !this.isPaused;
          break;
        case "ArrowUp":
          if (!this.isPaused) this.rotateCurrentPiece();
          break;
        case " ":
          if (event.repeat) return;
          if (this.isHardDropping) {
            this.isHardDropping = false;
            this.hardDrop();
          } else {
            this.togglePause();
          }
          break;
        case "Shift":
          if (!this.isPaused) this.isHardDropping = true;
          break;
        case "c":
        case "C":
          if (!this.isPaused) this.holdCurrentPiece();
          break;
        case "r":
        case "R":
          this.resetGame();
          break;
        default:
          return;
      }
      
      event.preventDefault();
    },
    
    /**
     * 处理键盘释放事件
     */
    handleKeyUp(event) {
      switch (event.key) {
        case "ArrowDown":
          this.isSoftDropping = false;
          break;
        case "Shift":
          this.isHardDropping = false;
          break;
      }
    },
    
    /**
     * 切换暂停状态
     */
    togglePause() {
      this.isPaused = !this.isPaused;
      if (!this.isPaused) {
        this.startTime = Date.now() - this.elapsedTime;
        this.lastFrameTime = performance.now();
        if (!this.animationFrameId) {
          this.gameLoop(this.lastFrameTime);
        }
      }
      this.focusGameContainer();
    },
    
    /**
     * 游戏结束
     */
    async gameOver() {
      // 停止游戏逻辑
      this.stopGame();
      
      // 添加游戏结束动画（例如闪烁效果）
      const originalGrid = JSON.parse(JSON.stringify(this.grid));
      let flashCount = 0;
      const maxFlashes = 5;
      const flashInterval = 150;
      
      const flashAnimation = setInterval(() => {
        flashCount++;
        
        // 交替显示空白网格和原始网格
        if (flashCount % 2 === 1) {
          this.grid = Array.from({ length: 20 }, () => Array(10).fill(0));
        } else {
          this.grid = JSON.parse(JSON.stringify(originalGrid));
        }
        
        this.draw();
        
        if (flashCount >= maxFlashes * 2) {
          clearInterval(flashAnimation);
          this.showGameOverDialog();
        }
      }, flashInterval);
    },

    showGameOverDialog() {
      // 创建自定义弹窗
      const gameOverDiv = document.createElement('div');
      gameOverDiv.style.position = 'fixed';
      gameOverDiv.style.top = '0';
      gameOverDiv.style.left = '0';
      gameOverDiv.style.width = '100%';
      gameOverDiv.style.height = '100%';
      gameOverDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
      gameOverDiv.style.display = 'flex';
      gameOverDiv.style.flexDirection = 'column';
      gameOverDiv.style.justifyContent = 'center';
      gameOverDiv.style.alignItems = 'center';
      gameOverDiv.style.zIndex = '1000';
      gameOverDiv.style.backdropFilter = 'blur(5px)';
      
      gameOverDiv.innerHTML = `
        <div style="background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
                    padding: 30px;
                    border-radius: 15px;
                    max-width: 400px;
                    width: 90%;
                    text-align: center;
                    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
                    border: 1px solid rgba(255, 255, 255, 0.1);">
          <h2 style="margin-top: 0; color: #ff5555; font-size: 28px;">游戏结束!</h2>
          <p style="font-size: 18px; margin: 15px 0;">你的得分: <strong style="color: #4CAF50;">${this.score}</strong></p>
          <p style="font-size: 16px; margin: 10px 0;">消除行数: <strong>${this.linesCleared}</strong></p>
          <p style="font-size: 16px; margin: 10px 0 25px;">等级: <strong>${this.level}</strong></p>
          <button id="restartGameBtn" style="padding: 12px 25px;
                      background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
                      color: white;
                      border: none;
                      border-radius: 8px;
                      cursor: pointer;
                      font-size: 16px;
                      font-weight: 600;
                      transition: all 0.3s ease;
                      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);">
            再来一局
          </button>
        </div>
      `;
      
      document.body.appendChild(gameOverDiv);
      
      // 添加事件监听器
      const restartBtn = document.getElementById('restartGameBtn');
      restartBtn.addEventListener('click', () => {
        gameOverDiv.remove();
        this.resetGame();
        this.focusGameContainer();
      });
    },
    
    /**
     * 清理资源
     */
    cleanup() {
      this.stopGame();
      window.removeEventListener("keydown", this.handleKeyDown);
      window.removeEventListener("keyup", this.handleKeyUp);
    }
  }
};
</script>

<style scoped>
.tetris-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
  color: #fff;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  user-select: none;
  outline: none;
  padding: 20px;
  box-sizing: border-box;
}

.game-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  max-width: 800px;
  margin-bottom: 25px;
  background: rgba(30, 30, 46, 0.8);
  padding: 15px 25px;
  border-radius: 12px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(5px);
}

.score-display {
  display: flex;
  gap: 25px;
}

.score-display span {
  font-size: 18px;
  font-weight: 500;
  color: #e2e2e2;
}

.score-display strong {
  color: #ffffff;
  font-weight: 700;
}

.restart-button {
  padding: 10px 20px;
  background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-size: 16px;
  font-weight: 600;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.restart-button:hover {
  background: linear-gradient(135deg, #43A047 0%, #1B5E20 100%);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.restart-button:active {
  transform: translateY(0);
}

.game-area {
  display: flex;
  gap: 25px;
  align-items: flex-start;
  max-width: 800px;
  width: 100%;
}

.left-panel, .right-panel {
  display: flex;
  flex-direction: column;
  gap: 25px;
  width: 180px;
}

.hold-piece-display, .next-piece-display, .time-display, .controls {
  background: rgba(30, 30, 46, 0.8);
  padding: 15px;
  border-radius: 12px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(5px);
  transition: transform 0.3s ease;
}

.hold-piece-display:hover, .next-piece-display:hover, 
.time-display:hover, .controls:hover {
  transform: translateY(-5px);
}

.hold-piece-display h3, .next-piece-display h3, 
.time-display h3, .controls h3 {
  margin-top: 0;
  margin-bottom: 15px;
  color: #ffffff;
  font-size: 18px;
  font-weight: 600;
  text-align: center;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.time-display strong {
  color: #4CAF50;
}

.controls {
  padding: 20px;
}

.controls p {
  margin: 8px 0;
  font-size: 14px;
  color: #d1d1d1;
  line-height: 1.5;
  text-align: left;
  position: relative;
  padding-left: 15px;
}

.controls p:before {
  content: "•";
  position: absolute;
  left: 0;
  color: #4CAF50;
}

canvas {
  background: rgba(30, 30, 46, 0.8);
  border: 2px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  transition: all 0.3s ease;
}

canvas:hover {
  border-color: rgba(255, 255, 255, 0.2);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .game-area {
    flex-direction: column;
    align-items: center;
  }
  
  .left-panel, .right-panel {
    width: 100%;
    max-width: 300px;
  }
  
  .game-info {
    flex-direction: column;
    gap: 15px;
    text-align: center;
  }
  
  .score-display {
    flex-direction: column;
    gap: 8px;
  }
}
.tetris-game:focus {
  outline: none;
  box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.5);
}
</style>